<template>
  <div ref="rootRef">
    <transition name="modal-view">
      <div class="modal-view" v-if="dialogVisible" v-viewdrag="{
        top: top,
        left: left,
        isStart: fullscreen ? false : isDrag
      }">
        <div class="modal-view-content" :class="{ 'modal-view-content-fullscreen': fullscreen }"
          :style="{ width, height }">
          <!-- 顶部 -->
          <div class="modal-view-header" v-if="!isHiddenHeader">
            <slot name="title">
              <div>{{ title }}</div>
            </slot>

            <div class="header-btn" v-if="!submitColse">
              <!-- <i class="el-icon-close" @click="close"></i> -->
              <img :src="gbicon" alt="" @click="close" style="width:20px;height:20px">
            </div>
          </div>
          <!-- 内容 -->
          <div class="modal-view-body" v-loading="loading || pageLoading">
            <slot></slot>
          </div>
          <!-- 底部栏 -->
          <div class="modal-view-footer">
            <div class="dialog-footer-left">
              <slot name="footerLeft"></slot>
            </div>
            <div class="dialog-footer-right">
              <slot name="table-column">
                <el-button type="primary" v-if="!hiddenSubmit" :loading="loading||pageLoading" @click="submit">{{ submitText }}
                </el-button>
                <el-button @click="close" v-if="!submitColse">{{ closeText }}</el-button>
              </slot>
            </div>
          </div>
        </div>
      </div>
    </transition>
  </div>
</template>

<script lang="ts">
import { defineComponent, nextTick as nextTick2 } from "vue";
import { ElLoadingDirective } from "element-plus";
export default defineComponent({
  name: "ModalView",
  directives: {
    loading: ElLoadingDirective,
    /**
     * 拖拽功能
     */
    viewdrag: {
      mounted(el, binding, vnode, oldVnode) {
        // console.log(binding);
        let { top, left, isStart } = binding.value;
        //拖拽单位
        let dragDom: HTMLElement = el.querySelector(
          ".modal-view-content"
        ) as HTMLElement;
        //对当前的div进行数据的初始化
        if (top === "auto") {
          dragDom.style.top = "10vh";
        } else {
          dragDom.style.top = top;
        }
        //因为左侧的数据是根据实际变化的，所以需要在页面已经渲染的时候
        //进行计算
        nextTick2(() => {
          if (left === "auto") {
            dragDom.style.left =
              el.offsetWidth / 2 - dragDom.offsetWidth / 2 + "px";
          } else {
            dragDom.style.left = left;
          }
        });
        if (!isStart) {
          return;
        }
        //拖拽句柄
        let dialogHandle: HTMLElement = el.querySelector(
          ".modal-view-header"
        ) as HTMLElement;
        dialogHandle.style.cursor = "move";
        dialogHandle.onmousedown = (e: any) => {
          // 鼠标按下，计算当前元素距离可视区的距离
          //这里面需要计算外边距的偏移量;
          const disX = e.clientX - dragDom.offsetLeft;
          const disY = e.clientY - dragDom.offsetTop;

          // // 获取到的值带px 正则匹配替换
          let css: any = getComputedStyle(dragDom, null);

          let isAddClass: boolean = false;
          let toLeftClassTime: any;
          let toTopClassTime: any;
          document.onmousemove = function (e) {
            if (!isAddClass) {
              dragDom.classList.add("modal-view-content-change");
              isAddClass = true;
            }
            // 通过事件委托，计算移动的距离
            const l = e.clientX - disX;
            const t = e.clientY - disY;

            if (l < 0) {
              //限制移动位置左侧不能超过父元素
              dragDom.style.left = "0px";
              el.classList.add("modal-view-to-left");
              clearTimeout(toLeftClassTime);
              toLeftClassTime = setTimeout(() => {
                el.classList.remove("modal-view-to-left");
              }, 500);
            } else {
              // 移动当前元素
              dragDom.style.left = `${l}px`;
            }
            if (t < 0) {
              //限制移动位置左侧不能超过父元素
              dragDom.style.top = "0px";
              el.classList.add("modal-view-to-top");
              clearTimeout(toTopClassTime);
              toTopClassTime = setTimeout(() => {
                el.classList.remove("modal-view-to-top");
              }, 500);
            } else {
              // 移动当前元素
              dragDom.style.top = `${t}px `;
            }
          };

          document.onmouseup = function (e) {
            document.onmousemove = null;
            document.onmouseup = null;
            dragDom.classList.remove("modal-view-content-change");
          };
        };
      }
    }
  }
})
</script>

<script lang="ts" setup>
import { ref, withDefaults, nextTick, resolveDirective, onMounted, onBeforeUnmount } from "vue";
import { ElButton } from "element-plus";
let gbicon = require("@/assets/icon/gb.svg");
let props = withDefaults(defineProps<{
  /**
   * 设置当前标题
   */
  title?: string;

  /**
   * 是否在loading中
   */
  loading?: boolean;


  /**
   * 是否隐藏当前顶部栏
   */
  isHiddenHeader?: boolean;

  /**
   * 是否需要添加到body中
   */
  appendToBody?: boolean;

  /**
   * 是否启动拖动
   */
  isDrag?: boolean;

  /**
   * 设置宽度
   */
  width?: string;

  /**
   * 设置改变大小的最小高度(只指内容)
   */
  height?: string;

  /**
   * 设置距离顶部
   */
  top?: string;

  /**
   * 设置距离左侧
   */
  left?: string;

  /**
   * 保存按钮的名称
   */
  submitText?: string;

  /**
   * 关闭按钮的名称
   */
  closeText?: string;

  /**
   * 是否隐藏保存按钮
   */
  hiddenSubmit?: boolean;

  /**
   * 是否只能通过保存关闭按钮
   * 如果为true, 则隐藏 关闭按钮 , 只保留保存按钮
   */
  submitColse?: boolean;

  /**
 * 是否为全屏
 * 注意  在全屏状态下，拖动跟更改大小将自动变为false
 */
  fullscreen?: boolean;

  /**
   * 点击保存的回调
   */
  beforeSubmit?: () => Promise<void>
}>(), {
  title: "编辑",
  isHiddenHeader: false,
  appendToBody: false,
  isDrag: true,
  width: "600px",
  height: "auto",
  top: "auto",
  left: "auto",
  submitText: "保存",
  closeText: "关闭",
  hiddenSubmit: false,
  submitColse: false,
  fullscreen: false,
  loading: false,
  beforeSubmit: () => {
    return Promise.resolve()
  }
})

let emit = defineEmits<{
  /**
   * 页面关闭
   */
  (e: "close"): void;
  /**
   * 点击页面保存按钮并成功
   */
  (e: "submit"): void
}>();


let rootRef = ref<HTMLElement>();

/**
 * 控制弹框打开
 */
let dialogVisible = ref(false);

/**
 * 全局loading中
 */
let pageLoading = ref(false);

onMounted(() => {
  window.addEventListener("keydown", onKeyDownEec)
})

onBeforeUnmount(() => {
  window.removeEventListener("keydown", onKeyDownEec)
})

/**
 *当点击esc的事件
 */
function onKeyDownEec(e: KeyboardEvent) {
  if (e.key == "Escape") {
    close();
  }
}

/**
 * 点击页面保存
 */
function submit() {
  pageLoading.value = true;
  props.beforeSubmit()
    .then(() => {
      emit("submit");
      close();
    })
    .finally(() => {
      pageLoading.value = false;
    })
}

/**
 * 页面打开
 */
function show() {
  dialogVisible.value = true;
}

/**
 * 页面关闭
 */
function close() {
  dialogVisible.value = false;
  nextTick(() => {
    setTimeout(() => {
      emit("close")
    }, 250)
  })
}

defineExpose({
  show,
  close
})

</script>

<style lang="less" scoped>
.el-modalview-body {
  /deep/ .el-overlay {
    position: absolute;
  }

  /deep/ .el-overlay-dialog {
    position: absolute;
  }
}

@keyframes ModalShow {
  0% {
    opacity: 0;
  }

  100% {
    opacity: 1;
  }
}

.modal-view {
  z-index: var(--zindexModalView);
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.5);
  overflow: auto;

  &::after {
    content: "";
    position: absolute;
    left: 0;
    top: 0;
    height: 100%;
    transition: 0.3s;
  }

  &::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    transition: 0.3s;
  }

  // animation: ModalShow 0.2s linear;
  .modal-view-content {
    border-radius: 3px;
    background-color: white;
    position: absolute;
    display: flex;
    flex-direction: column;
    overflow-y: auto;

    .modal-view-header {
      // background-color: var(--primaryColor10);
      padding: 10px;
      font-size: 16px;
      font-weight: bold;
      display: flex;
      justify-content: space-between;
      align-items: center;
      user-select: none;
      flex-shrink: 0;

      // 顶部按钮组
      .header-btn {
        cursor: pointer;

        &:hover {
          color: var(--mainColor);
        }
      }
    }

    // 内部主要功能
    .modal-view-body {
      padding: 5px 15px;
      flex-grow: 1;
      height: 100%;
      overflow: auto;
    }

    // 底部
    .modal-view-footer {
      padding: 10px;
      display: flex;
      justify-content: space-between;
      align-items: stretch;
      width: 100%;
      position: relative;
      padding: 10px;

      .dialog-footer-left {
        flex: 1;
        width: 0;
        display: flex;
        align-items: center;
      }

      .dialog-footer-right {
        flex-shrink: 0;
        margin: auto 0;
      }
    }
  }

  //当选择全屏的时候
  .modal-view-content-fullscreen {
    width: calc(100% - 20px) !important;
    height: calc(100% - 20px) !important;
    top: 10px !important;
    left: 10px !important;
    border: 1px solid rgba(199, 197, 197, 0.5);
  }

  // 当当前窗口被改变的时候，包括拖动跟改变大小
  .modal-view-content-change {
    opacity: 0.5;
    user-select: none;
  }
}

// 当页面拖动到左侧不能拖动的时候
.modal-view-to-left {
  &::after {
    content: "";
    box-shadow: 2px 0px 15px 2px rgba(255, 0, 0, 1);
  }
}

.modal-view-to-top {
  &::before {
    content: "";
    box-shadow: 0px 2px 15px 2px rgba(255, 0, 0, 1);
  }
}

// 过渡效果
.modal-view-enter-active,
.modal-view-leave-active {
  transition: opacity 0.25s;

  .modal-view-content {
    transition: 0.25s;
  }
}

.modal-view-enter-from,
.modal-view-leave-to

/* .fade-leave-active below version 2.1.8 */
  {
  opacity: 0;

  .modal-view-content {
    transform: translateY(-10px);
  }
}
</style>
